/**
 * 键盘事件工具函数 - TypeScript版本
 * 提供键盘事件监听、按键禁用、组合键处理等功能
 * 支持直接复制粘贴使用，无需任何依赖
 * 每个函数都是独立的，可以单独复制使用
 */

// 类型定义
export interface KeyboardEventConfig {
  key?: string;
  code?: string;
  ctrlKey?: boolean;
  shiftKey?: boolean;
  altKey?: boolean;
  metaKey?: boolean;
  preventDefault?: boolean;
  stopPropagation?: boolean;
  once?: boolean;
}

export interface KeyboardListener {
  id: string;
  eventType: string;
  config: KeyboardEventConfig;
  handler: (event: KeyboardEvent) => void;
  element: HTMLElement;
  active: boolean;
  eventHandler?: (event: KeyboardEvent) => void;
}

export interface NavigationConfig {
  selector?: string;
  loop?: boolean;
  orientation?: 'vertical' | 'horizontal';
}

export interface CrossPlatformShortcuts {
  mac?: string;
  windows?: string;
  linux?: string;
  default?: string;
}

// 常量定义
export const KEYBOARD_EVENT_TYPES = {
  KEYDOWN: 'keydown',
  KEYUP: 'keyup',
  KEYPRESS: 'keypress'
} as const;

export const PLATFORMS = {
  MAC: 'mac',
  WINDOWS: 'windows',
  LINUX: 'linux',
  UNKNOWN: 'unknown'
} as const;

// 全局监听器存储
let listeners = new Map<string, KeyboardListener>();
let disabledKeys = new Set<string>();
let navigationConfig: NavigationConfig | null = null;

/**
 * 检测平台
 * @returns {string} 平台类型
 */
export function detectPlatform(): string {
  const userAgent = navigator.userAgent.toLowerCase();
  const platform = navigator.platform.toLowerCase();
  
  if (userAgent.includes('mac') || platform.includes('mac')) {
    return PLATFORMS.MAC;
  } else if (userAgent.includes('win') || platform.includes('win')) {
    return PLATFORMS.WINDOWS;
  } else if (userAgent.includes('linux') || platform.includes('linux')) {
    return PLATFORMS.LINUX;
  }
  
  return PLATFORMS.UNKNOWN;
}

/**
 * 获取当前平台
 * @returns {string} 平台类型
 */
export function getPlatform(): string {
  return detectPlatform();
}

/**
 * 检查是否为Mac系统
 * @returns {boolean} 是否为Mac系统
 */
export function isMacOS(): boolean {
  return getPlatform() === PLATFORMS.MAC;
}

/**
 * 获取平台修饰键
 * @param {string} key - 基础键
 * @returns {string} 平台修饰键
 */
export function getPlatformModifier(key: string): string {
  const platform = getPlatform();
  
  if (platform === PLATFORMS.MAC) {
    return key.replace('ctrl', 'cmd');
  }
  
  return key;
}

/**
 * 获取平台快捷键显示文本
 * @param {string} shortcut - 快捷键
 * @returns {string} 显示文本
 */
export function getPlatformShortcutText(shortcut: string): string {
  const platform = getPlatform();
  
  if (platform === PLATFORMS.MAC) {
    return shortcut
      .replace(/ctrl/gi, '⌘')
      .replace(/alt/gi, '⌥')
      .replace(/shift/gi, '⇧')
      .replace(/meta/gi, '⌘');
  }
  
  return shortcut;
}

/**
 * 添加键盘监听器
 * @param {string} id - 监听器ID
 * @param {string} eventType - 事件类型
 * @param {KeyboardEventConfig} config - 事件配置
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addListener(
  id: string, 
  eventType: string, 
  config: KeyboardEventConfig = {}, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  // 检查是否已存在相同ID的监听器
  if (listeners.has(id)) {
    console.warn(`监听器 ${id} 已存在，将被替换`);
    removeListener(id);
  }
  
  const listener: KeyboardListener = {
    id,
    eventType,
    config,
    handler,
    element,
    active: true
  };
  
  const eventHandler = (event: KeyboardEvent) => {
    if (!listener.active) return;
    
    // 检查按键是否被禁用
    if (disabledKeys.has(event.key) || disabledKeys.has(event.code)) {
      event.preventDefault();
      return;
    }
    
    // 检查事件配置
    if (config.key && event.key !== config.key) return;
    if (config.code && event.code !== config.code) return;
    if (config.ctrlKey !== undefined && event.ctrlKey !== config.ctrlKey) return;
    if (config.shiftKey !== undefined && event.shiftKey !== config.shiftKey) return;
    if (config.altKey !== undefined && event.altKey !== config.altKey) return;
    if (config.metaKey !== undefined && event.metaKey !== config.metaKey) return;
    
    // 执行处理函数
    if (config.preventDefault) {
      event.preventDefault();
    }
    if (config.stopPropagation) {
      event.stopPropagation();
    }
    
    handler(event);
    
    // 如果是一次性监听器，移除它
    if (config.once) {
      removeListener(id);
    }
  };
  
  element.addEventListener(eventType, eventHandler as EventListener);
  listener.eventHandler = eventHandler;
  
  listeners.set(id, listener);
  
  // 返回移除监听器的函数
  return () => removeListener(id);
}

/**
 * 移除键盘监听器
 * @param {string} id - 监听器ID
 */
export function removeListener(id: string): void {
  const listener = listeners.get(id);
  if (listener) {
    listener.element.removeEventListener(listener.eventType, listener.eventHandler as EventListener);
    listeners.delete(id);
  }
}

/**
 * 移除所有监听器
 */
export function removeAllListeners(): void {
  listeners.forEach((listener) => {
    listener.element.removeEventListener(listener.eventType, listener.eventHandler as EventListener);
  });
  listeners.clear();
}

/**
 * 添加回车键监听器
 * @param {string} id - 监听器ID
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addEnterListener(
  id: string, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  return addListener(id, KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: 'Enter',
    preventDefault: true
  }, handler, element);
}

/**
 * 添加ESC键监听器
 * @param {string} id - 监听器ID
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addEscapeListener(
  id: string, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  return addListener(id, KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: 'Escape',
    preventDefault: true
  }, handler, element);
}

/**
 * 添加Tab键监听器
 * @param {string} id - 监听器ID
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addTabListener(
  id: string, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  return addListener(id, KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: 'Tab',
    preventDefault: true
  }, handler, element);
}

/**
 * 添加空格键监听器
 * @param {string} id - 监听器ID
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addSpaceListener(
  id: string, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  return addListener(id, KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: ' ',
    preventDefault: true
  }, handler, element);
}

/**
 * 添加快捷键监听器
 * @param {string} id - 监听器ID
 * @param {string} shortcut - 快捷键字符串
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addShortcut(
  id: string, 
  shortcut: string, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  const keys = shortcut.toLowerCase().split('+').map(key => key.trim());
  
  let config: KeyboardEventConfig = {};
  
  // 解析修饰键
  if (keys.includes('ctrl')) config.ctrlKey = true;
  if (keys.includes('shift')) config.shiftKey = true;
  if (keys.includes('alt')) config.altKey = true;
  if (keys.includes('meta') || keys.includes('cmd')) config.metaKey = true;
  
  // 获取主键
  const mainKey = keys[keys.length - 1];
  config.key = mainKey;
  config.preventDefault = true;
  
  return addListener(id, KEYBOARD_EVENT_TYPES.KEYDOWN, config, handler, element);
}

/**
 * 添加Mac兼容的快捷键监听器
 * @param {string} id - 监听器ID
 * @param {string} shortcut - 快捷键字符串
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addMacCompatibleShortcut(
  id: string, 
  shortcut: string, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  const platform = getPlatform();
  let actualShortcut = shortcut;
  
  if (platform === PLATFORMS.MAC) {
    actualShortcut = shortcut.replace(/ctrl/gi, 'cmd');
  }
  
  return addShortcut(id, actualShortcut, handler, element);
}

/**
 * 添加跨平台快捷键监听器
 * @param {string} id - 监听器ID
 * @param {CrossPlatformShortcuts} shortcuts - 平台快捷键配置
 * @param {Function} handler - 处理函数
 * @param {HTMLElement} [element] - 目标元素
 * @returns {Function} 移除监听器的函数
 */
export function addCrossPlatformShortcut(
  id: string, 
  shortcuts: CrossPlatformShortcuts, 
  handler: (event: KeyboardEvent) => void, 
  element: HTMLElement = document as any
): () => void {
  const platform = getPlatform();
  const shortcut = shortcuts[platform as keyof CrossPlatformShortcuts] || shortcuts.default || shortcuts;
  
  return addShortcut(id, shortcut as string, handler, element);
}

/**
 * 禁用特定按键
 * @param {string} key - 要禁用的按键
 */
export function disableKey(key: string): void {
  disabledKeys.add(key);
}

/**
 * 启用特定按键
 * @param {string} key - 要启用的按键
 */
export function enableKey(key: string): void {
  disabledKeys.delete(key);
}

/**
 * 禁用所有常用按键
 */
export function disableAllKeys(): void {
  const commonKeys = [
    'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12',
    'Tab', 'CapsLock', 'Shift', 'Control', 'Alt', 'Meta',
    'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',
    'PageUp', 'PageDown', 'Home', 'End', 'Insert', 'Delete',
    'Backspace', 'Enter', 'Escape'
  ];
  
  commonKeys.forEach(key => disabledKeys.add(key));
}

/**
 * 启用所有按键
 */
export function enableAllKeys(): void {
  disabledKeys.clear();
}

/**
 * 检查是否按下了组合键
 * @param {KeyboardEvent} event - 键盘事件
 * @param {Array} keys - 按键数组
 * @returns {boolean} 是否按下了组合键
 */
export function isComboPressed(event: KeyboardEvent, keys: string[]): boolean {
  const pressedKeys: string[] = [];
  
  if (event.ctrlKey) pressedKeys.push('ctrl');
  if (event.shiftKey) pressedKeys.push('shift');
  if (event.altKey) pressedKeys.push('alt');
  if (event.metaKey) pressedKeys.push('meta');
  pressedKeys.push(event.key.toLowerCase());
  
  return keys.every(key => pressedKeys.includes(key.toLowerCase()));
}

/**
 * 获取当前按下的修饰键
 * @param {KeyboardEvent} event - 键盘事件
 * @returns {Array} 修饰键数组
 */
export function getPressedModifiers(event: KeyboardEvent): string[] {
  const modifiers: string[] = [];
  
  if (event.ctrlKey) modifiers.push('ctrl');
  if (event.shiftKey) modifiers.push('shift');
  if (event.altKey) modifiers.push('alt');
  if (event.metaKey) modifiers.push('meta');
  
  return modifiers;
}

/**
 * 设置键盘导航
 * @param {NavigationConfig} config - 导航配置
 */
export function setupNavigation(config: NavigationConfig): void {
  navigationConfig = {
    selector: config.selector || '.nav-item',
    loop: config.loop !== false,
    orientation: config.orientation || 'vertical',
    ...config
  };
  
  // 添加键盘导航监听器
  addListener('keyboard-navigation', KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: 'Tab',
    preventDefault: true
  }, handleNavigation);
  
  addListener('keyboard-navigation-arrows', KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: navigationConfig.orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight',
    preventDefault: true
  }, handleNavigation);
  
  addListener('keyboard-navigation-arrows-reverse', KEYBOARD_EVENT_TYPES.KEYDOWN, {
    key: navigationConfig.orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft',
    preventDefault: true
  }, handleNavigation);
}

/**
 * 处理键盘导航
 * @param {KeyboardEvent} event - 键盘事件
 */
function handleNavigation(event: KeyboardEvent): void {
  if (!navigationConfig) return;
  
  const elements = document.querySelectorAll(navigationConfig.selector!);
  const currentElement = document.activeElement;
  const currentIndex = Array.from(elements).indexOf(currentElement);
  
  let nextIndex = currentIndex;
  
  if (event.key === 'Tab') {
    nextIndex = event.shiftKey ? currentIndex - 1 : currentIndex + 1;
  } else if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {
    nextIndex = currentIndex + 1;
  } else if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {
    nextIndex = currentIndex - 1;
  }
  
  // 处理循环导航
  if (navigationConfig.loop) {
    if (nextIndex < 0) nextIndex = elements.length - 1;
    if (nextIndex >= elements.length) nextIndex = 0;
  } else {
    if (nextIndex < 0) nextIndex = 0;
    if (nextIndex >= elements.length) nextIndex = elements.length - 1;
  }
  
  if (nextIndex !== currentIndex && elements[nextIndex]) {
    (elements[nextIndex] as HTMLElement).focus();
  }
}

/**
 * 清理所有键盘事件
 */
export function cleanup(): void {
  removeAllListeners();
  enableAllKeys();
  navigationConfig = null;
}

/**
 * 获取所有监听器
 * @returns {Array} 监听器数组
 */
export function getAllListeners(): KeyboardListener[] {
  return Array.from(listeners.values());
}

/**
 * 获取监听器数量
 * @returns {number} 监听器数量
 */
export function getListenerCount(): number {
  return listeners.size;
}

/**
 * 检查监听器是否存在
 * @param {string} id - 监听器ID
 * @returns {boolean} 是否存在
 */
export function hasListener(id: string): boolean {
  return listeners.has(id);
}

/**
 * 暂停监听器
 * @param {string} id - 监听器ID
 */
export function pauseListener(id: string): void {
  const listener = listeners.get(id);
  if (listener) {
    listener.active = false;
  }
}

/**
 * 恢复监听器
 * @param {string} id - 监听器ID
 */
export function resumeListener(id: string): void {
  const listener = listeners.get(id);
  if (listener) {
    listener.active = true;
  }
}

/**
 * 暂停所有监听器
 */
export function pauseAllListeners(): void {
  listeners.forEach(listener => {
    listener.active = false;
  });
}

/**
 * 恢复所有监听器
 */
export function resumeAllListeners(): void {
  listeners.forEach(listener => {
    listener.active = true;
  });
}